package com.uxsino.commons.utils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.configuration2.Configuration;
import org.apache.commons.configuration2.FileBasedConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;
import org.w3c.dom.Document;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.Session;
import com.uxsino.commons.baseclass.Constants;

public class SimoResourceUtil {

    static Path currentRelativePath;

    static String currentRelativeDir;

    private final static Logger logger = LoggerFactory.getLogger(SimoResourceUtil.class);

    public static Document getDocumentFromFile(String xmlFileName) {
        String xmlString = readSpringResourceToString(xmlFileName);
        Document doc = getDocumentFromString(xmlString);
        return doc;
    }

    public final static String getCurrentRunningPath() {
        if (currentRelativeDir == null) {
            Path currentRelativePath = Paths.get("");
            currentRelativeDir = currentRelativePath.toAbsolutePath().toString();
            logger.info("Current relative path is: " + currentRelativeDir);
        }
        return currentRelativeDir;
    }

    public static String readFileToString(String fileName) {
        String content = null;
        InputStream in = null;
        try {
            in = new FileInputStream(currentRelativeDir + fileName);
            content = IOUtils.toString(in, StandardCharsets.UTF_8);
            in.close(); // close errors are handled
        } catch (Exception e) {
            logger.warn("Error reading file {}, try to read it from jar", currentRelativeDir + fileName, e);
            content = readSpringResourceToString(fileName);
        } finally {
            IOUtils.closeQuietly(in);
        }

        return content;
    }

    public static String readSpringResourceToString(String fileName) {
        String content = "";
        ClassPathResource cpr = new ClassPathResource("/" + fileName);
        try {
            byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
            content = new String(bdata, StandardCharsets.UTF_8);
        } catch (FileNotFoundException efn) {
            logger.warn("File not found. {}", fileName);
        } catch (IOException e) {
            logger.error("Error reading file {}", fileName);
        }
        return content;
    }

    public static void readFileFromDir(String path, List<File> files) {
        ClassPathResource resource = new ClassPathResource(path);
        File file = null;
        try {
            file = resource.getFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (file == null) {
            return;
        }
        if (file.isDirectory()) {
            for (String fileName : file.list()) {
                readFileFromDir(path + File.separator + fileName, files);
            }
        } else {
            files.add(file);
        }
    }

    public static Document getDocumentFromString(String xmlString) {
        InputStream in = new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8));
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = null;
        Document doc = null;

        try {
            dBuilder = dbFactory.newDocumentBuilder();
        } catch (Exception e) {
            logger.error("cannot init xml Builder. ", e);
        }
        try {
            doc = dBuilder.parse(in);
        } catch (Exception e) {
            logger.error("cannot parse xml. ", e);
        }
        doc.getDocumentElement().normalize();
        return doc;
    }

    public static Configuration getConfig(String fileName) {
        Parameters params = new Parameters();
        FileBasedConfigurationBuilder<FileBasedConfiguration> builder = new FileBasedConfigurationBuilder<FileBasedConfiguration>(
            PropertiesConfiguration.class).configure(params.properties().setFileName(fileName));
        try {
            Configuration config = builder.getConfiguration();
            return config;
        } catch (ConfigurationException cex) {
            logger.error("loading of the configuration file failed " + fileName, cex);
        }
        return null;
    }

    public static void disconnect(Channel channel) {
        try {
            if (channel != null) {
                channel.disconnect();
            }
        } catch (Exception e) {
        }
    }

    public static void disconnect(Session channel) {
        try {
            if (channel != null) {
                channel.disconnect();
            }
        } catch (Exception e) {
        }
    }

    public static void close(Reader reader) {
        try {
            if (reader != null) {
                reader.close();
            }
        } catch (IOException e) {
        }
    }

    public static void close(InputStream reader) {
        try {
            if (reader != null) {
                reader.close();
            }
        } catch (IOException e) {
        }
    }

    public static String getLicenseFilePath(final String uploadPath) {
        return getUploadPath(uploadPath) + Constants.SEPARATOR + Constants.LICENSE_PATH;
    }

    public static String getUploadPath(final String uploadPath) {
        String path = getCurrentRunningPath() + Constants.SEPARATOR;
        if (uploadPath.startsWith("/")) {
            path += uploadPath.substring(0);
        } else {
            path += uploadPath;
        }
        // 定义上传路径
        return path;
    }
}
